package com.sh.cloudrender.infrastructure.repository;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.sh.cloudrender.application.dto.engine.EngineDTO;
import com.sh.cloudrender.application.dto.engine.EngineSpec;
import com.sh.cloudrender.infrastructure.dal.dao.EngineDao;
import com.sh.cloudrender.infrastructure.dal.dao.UserEngineRelDao;
import com.sh.cloudrender.infrastructure.dal.entity.EngineDO;
import com.sh.cloudrender.infrastructure.dal.entity.UserEngineRel;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

@Repository
public class EngineRepoImpl implements EngineRepo {

    @Autowired
    private EngineDao engineDao;

    @Autowired
    private UserEngineRelDao userEngineRelDao;


    @Override
    @Transactional
    public boolean saveOrUpdate(String userId, EngineDTO engineDTO) {
        // 检查 engineDTO 和其内部的 spec 是否为 null
        if (engineDTO == null) {
            throw new IllegalArgumentException("EngineDTO and its Spec must not be null");
        }

        EngineDO engineDO = new EngineDO();
        BeanUtils.copyProperties(engineDTO, engineDO);
        engineDO.setCpus(engineDTO.getSpec().getCpus());
        engineDO.setMemory(engineDTO.getSpec().getMemory());
        engineDO.setEnableGpu(engineDTO.getSpec().getEnableGpu());
        UpdateWrapper<EngineDO> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("engine_id", engineDTO.getEngineId());
        if (engineDao.saveOrUpdate(engineDO)) {
            UserEngineRel userEngineRel = new UserEngineRel();
            userEngineRel.setUserId(userId);
            userEngineRel.setEngineId(engineDTO.getEngineId());
            return userEngineRelDao.save(userEngineRel);
        }

        return false;
    }

    @Override
    @Transactional
    public boolean deleteByEngineId(String engineId) {
        QueryWrapper<EngineDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("engine_id", engineId);
        if (engineDao.remove(queryWrapper)) {
            QueryWrapper<UserEngineRel> deleteWrapper = new QueryWrapper<>();
            deleteWrapper.eq("engine_id", engineId);
            return userEngineRelDao.remove(deleteWrapper);
        }

        return false;
    }

    @Override
    @Transactional
    public boolean deleteByUserId(String userId) {
        QueryWrapper<UserEngineRel> queryUserEngineRelWrapper = new QueryWrapper<>();
        queryUserEngineRelWrapper.eq("user_id", userId);
        List<UserEngineRel> engineRels = userEngineRelDao.list(queryUserEngineRelWrapper);
        if (CollectionUtils.isEmpty(engineRels)) {
            return true;
        }

        QueryWrapper<EngineDO> deleteEngineWrapper = new QueryWrapper<>();
        deleteEngineWrapper.in("engine_id", engineRels.stream().map(UserEngineRel::getEngineId)
                .collect(Collectors.toList()).toArray());
        if (engineDao.remove(deleteEngineWrapper)) {
            QueryWrapper<UserEngineRel> deleteWrapper = new QueryWrapper<>();
            deleteWrapper.eq("user_id", userId);
            return userEngineRelDao.remove(deleteWrapper);
        }

        return false;
    }

    @Override
    public List<EngineDTO> findByUserId(String userId) {
        QueryWrapper<UserEngineRel> queryUserEngineRelWrapper = new QueryWrapper<>();
        queryUserEngineRelWrapper.eq("user_id", userId);
        List<UserEngineRel> engineRels = userEngineRelDao.list(queryUserEngineRelWrapper);
        if (CollectionUtils.isEmpty(engineRels)) {
            return null;
        }

        QueryWrapper<EngineDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("engine_id", engineRels.stream().map(UserEngineRel::getEngineId)
                .collect(Collectors.toList()).toArray());
        List<EngineDO> engineDOS = engineDao.list(queryWrapper);
        if (CollectionUtils.isEmpty(engineDOS)) {
            return null;
        }

        return engineDOS.stream().map(item -> parse(item)).collect(Collectors.toList());
    }

    @Override
    public EngineDTO findByEngineId(String engineId) {
        QueryWrapper<EngineDO> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("engine_id", engineId);
        EngineDO engineDO = engineDao.getOne(queryWrapper);
        if (engineDO == null) {
            return null;
        }

        return parse(engineDO);
    }

    private EngineDTO parse(EngineDO engineDO) {
        EngineDTO dto = new EngineDTO();
        BeanUtils.copyProperties(engineDO, dto);
        EngineSpec spec = new EngineSpec();
        spec.setCpus(engineDO.getCpus());
        spec.setMemory(engineDO.getMemory());
        spec.setEnableGpu(engineDO.getEnableGpu());
        dto.setSpec(spec);
        return dto;
    }
}
